package it.unibo.refolding.common;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LoggingInvocationHandler implements InvocationHandler {

	private static final Logger logger = Logger.getLogger(LoggingInvocationHandler.class
		.getSimpleName());

	private final Level level;
	private final Object delegate;

	public LoggingInvocationHandler(Level level, Object delegate) {
		this.level = level;
		this.delegate = delegate;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		assert args == null || args.length != 0;
		Object result;
		Throwable thrown;
		try {
			result = method.invoke(delegate, args);
			thrown = null;
		} catch (InvocationTargetException e) {
			result = null;
			thrown = e.getCause();
		}
		logger.log(level, "Method: {0} Args: {1} Result: {2} Exception: {3}", new Object[] {
			method, args == null ? null : Arrays.asList(args), result, thrown });
		if (thrown != null) {
			if (thrown instanceof RuntimeException) {
				throw (RuntimeException) thrown;
			} else if (thrown instanceof Error) {
				throw (Error) thrown;
			} else {
				throw new IllegalStateException("impossible");
			}
		}
		return result;
	}
}
